home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 16 / CU Amiga Magazine's Super CD-ROM 16 (1997-10-16)(EMAP Images)(GB)[!][issue 1997-11].iso / CUCD / Graphics / Ghostscript / source / zfont2.c < prev    next >
C/C++ Source or Header  |  1997-07-08  |  16KB  |  542 lines

  1. /* Copyright (C) 1989, 1995, 1996, 1997 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* zfont2.c */
  20. /* Font creation utilities */
  21. #include "memory_.h"
  22. #include "string_.h"
  23. #include "ghost.h"
  24. #include "errors.h"
  25. #include "oper.h"
  26. #include "gxfixed.h"
  27. #include "gsmatrix.h"
  28. #include "gxdevice.h"
  29. #include "gschar.h"
  30. #include "gxfont.h"
  31. #include "bfont.h"
  32. #include "ialloc.h"
  33. #include "idict.h"
  34. #include "idparam.h"
  35. #include "ilevel.h"
  36. #include "iname.h"
  37. #include "ipacked.h"
  38. #include "istruct.h"
  39. #include "store.h"
  40.  
  41. /* Registered encodings.  See ifont.h for documentation. */
  42. ref registered_Encodings;
  43. private ref *registered_Encodings_p = ®istered_Encodings;
  44. private gs_gc_root_t registered_Encodings_root;
  45.  
  46. /* Structure descriptor */
  47. public_st_font_data();
  48.  
  49. /* Initialize the font building operators */
  50. private void
  51. zfont2_init(void)
  52. {    /* Initialize the registered Encodings. */
  53.     {    int i;
  54.         ialloc_ref_array(®istered_Encodings, a_readonly,
  55.                  registered_Encodings_countof,
  56.                  "registered_Encodings");
  57.         for ( i = 0; i < registered_Encodings_countof; i++ )
  58.           make_empty_array(®istered_Encoding(i), 0);
  59.     }
  60.     gs_register_ref_root(imemory, ®istered_Encodings_root,
  61.                  (void **)®istered_Encodings_p,
  62.                  "registered_Encodings");
  63. }
  64.  
  65. /* <string|name> <font_dict> .buildfont3 <string|name> <font> */
  66. /* Build a type 3 (user-defined) font. */
  67. private int
  68. zbuildfont3(os_ptr op)
  69. {    int code;
  70.     build_proc_refs build;
  71.     gs_font_base *pfont;
  72.  
  73.     check_type(*op, t_dictionary);
  74.     code = build_gs_font_procs(op, &build);
  75.     if ( code < 0 )
  76.       return code;
  77.     code = build_gs_simple_font(op, &pfont, ft_user_defined,
  78.                     &st_gs_font_base, &build, bf_options_none);
  79.     if ( code < 0 )
  80.       return code;
  81.     return define_gs_font((gs_font *)pfont);
  82. }
  83.  
  84. /* <int> <array|shortarray> .registerencoding - */
  85. private int
  86. zregisterencoding(register os_ptr op)
  87. {    long i;
  88.     if ( !r_is_array(op) )
  89.       return_op_typecheck(op);
  90.     check_read(*op);
  91.     check_type(op[-1], t_integer);
  92.     for ( i = r_size(op); i > 0; )
  93.       {    ref cname;
  94.         array_get(op, --i, &cname);
  95.         check_type_only(cname, t_name);
  96.       }
  97.     i = op[-1].value.intval;
  98.     if ( i >= 0 && i < registered_Encodings_countof )
  99.     {    ref *penc = ®istered_Encoding(i);
  100.         ref_assign_old(®istered_Encodings, penc, op,
  101.                    ".registerencoding");
  102.     }
  103.     pop(2);
  104.     return 0;
  105. }
  106.  
  107. /* Encode a character. */
  108. private gs_glyph
  109. zfont_encode_char(gs_show_enum *penum, gs_font *pfont, gs_char *pchr)
  110. {    const ref *pencoding = &pfont_data(pfont)->Encoding;
  111.     ulong index = *pchr;    /* work around VAX widening bug */
  112.     ref cname;
  113.     int code = array_get(pencoding, (long)index, &cname);
  114.     if ( code < 0 || !r_has_type(&cname, t_name) )
  115.       return gs_no_glyph;
  116.     return (gs_glyph)name_index(&cname);
  117. }
  118.  
  119. /* Encode a character in a known encoding. */
  120. private gs_glyph
  121. zfont_known_encode(gs_char chr, int encoding_index)
  122. {    ulong index = chr;    /* work around VAX widening bug */
  123.     ref cname;
  124.     int code;
  125.     if ( encoding_index < 0 )
  126.       return gs_no_glyph;
  127.     code = array_get(®istered_Encoding(encoding_index),
  128.              (long)index, &cname);
  129.     if ( code < 0 || !r_has_type(&cname, t_name) )
  130.       return gs_no_glyph;
  131.     return (gs_glyph)name_index(&cname);
  132. }
  133.  
  134. /* Get the name of a glyph. */
  135. /* The following typedef is needed to work around a bug in */
  136. /* some AIX C compilers. */
  137. typedef const char *const_chars;
  138. private const_chars
  139. zfont_glyph_name(gs_glyph index, uint *plen)
  140. {    ref nref, sref;
  141.  
  142.     if ( index >= gs_min_cid_glyph )
  143.       { /* Fabricate a numeric name. */
  144.         char cid_name[sizeof(gs_glyph) * 3 + 1];
  145.         int code;
  146.  
  147.         sprintf(cid_name, "%lu", (ulong)index);
  148.         code = name_ref((const byte *)cid_name, strlen(cid_name),
  149.                 &nref, 1);
  150.         if ( code < 0 )
  151.           return 0;        /* What can we possibly do here? */
  152.       }
  153.     else
  154.       name_index_ref(index, &nref);
  155.     name_string_ref(&nref, &sref);
  156.     *plen = r_size(&sref);
  157.     return (const char *)sref.value.const_bytes;
  158. }
  159.  
  160. /* ------ Initialization procedure ------ */
  161.  
  162. BEGIN_OP_DEFS(zfont2_op_defs) {
  163.     {"2.buildfont3", zbuildfont3},
  164.     {"2.registerencoding", zregisterencoding},
  165. END_OP_DEFS(zfont2_init) }
  166.  
  167. /* ------ Subroutines ------ */
  168.  
  169. /* Convert strings to executable names for build_proc_refs. */
  170. int
  171. build_proc_name_refs(build_proc_refs *pbuild,
  172.   const char _ds *bcstr, const char _ds *bgstr)
  173. {    int code;
  174.  
  175.     if ( !bcstr )
  176.       make_null(&pbuild->BuildChar);
  177.     else
  178.       { if ( (code = name_ref((const byte *)bcstr, strlen(bcstr), &pbuild->BuildChar, 0)) < 0 )
  179.           return code;
  180.         r_set_attrs(&pbuild->BuildChar, a_executable);
  181.       }
  182.     if ( !bgstr )
  183.       make_null(&pbuild->BuildGlyph);
  184.     else
  185.       { if ( (code = name_ref((const byte *)bgstr, strlen(bgstr), &pbuild->BuildGlyph, 0)) < 0 )
  186.           return code;
  187.         r_set_attrs(&pbuild->BuildGlyph, a_executable);
  188.       }
  189.     return 0;
  190. }
  191.  
  192. /* Get the BuildChar and/or BuildGlyph routines from a (base) font. */
  193. int
  194. build_gs_font_procs(os_ptr op, build_proc_refs *pbuild)
  195. {    int ccode, gcode;
  196.     ref *pBuildChar;
  197.     ref *pBuildGlyph;
  198.  
  199.     check_type(*op, t_dictionary);
  200.     ccode = dict_find_string(op, "BuildChar", &pBuildChar);
  201.     gcode = dict_find_string(op, "BuildGlyph", &pBuildGlyph);
  202.     if ( ccode <= 0 )
  203.     {    if ( gcode <= 0 )
  204.           return_error(e_invalidfont);
  205.         make_null(&pbuild->BuildChar);
  206.     }
  207.     else
  208.     {    check_proc(*pBuildChar);
  209.         pbuild->BuildChar = *pBuildChar;
  210.     }
  211.     if ( gcode <= 0 )
  212.       make_null(&pbuild->BuildGlyph);
  213.     else
  214.     {    check_proc(*pBuildGlyph);
  215.         pbuild->BuildGlyph = *pBuildGlyph;
  216.     }
  217.     return 0;
  218. }
  219.  
  220. /* Do the common work for building a primitive font -- one whose execution */
  221. /* algorithm is implemented in C (Type 1, Type 4, or Type 42). */
  222. /* The caller guarantees that *op is a dictionary. */
  223. int
  224. build_gs_primitive_font(os_ptr op, gs_font_base **ppfont, font_type ftype,
  225.   gs_memory_type_ptr_t pstype, const build_proc_refs *pbuild,
  226.   build_font_options_t options)
  227. {    int painttype;
  228.     float strokewidth;
  229.     ref *pcharstrings = 0;
  230.     gs_font_base *pfont;
  231.     font_data *pdata;
  232.     int code;
  233.  
  234.     code = dict_int_param(op, "PaintType", 0, 3, 0, &painttype);
  235.     if ( code < 0 )
  236.       return code;
  237.     code = dict_float_param(op, "StrokeWidth", 0.0, &strokewidth);
  238.     if ( code < 0 )
  239.       return code;
  240.     if ( dict_find_string(op, "CharStrings", &pcharstrings) <= 0 )
  241.       { if ( !(options & bf_CharStrings_optional) )
  242.           return_error(e_invalidfont);
  243.       }
  244.     else
  245.       { if ( !r_has_type(pcharstrings, t_dictionary) )
  246.           return_error(e_invalidfont);
  247.       }
  248.     code = build_gs_simple_font(op, &pfont, ftype, pstype, pbuild, options);
  249.     if ( code != 0 )
  250.       return code;
  251.     pfont->PaintType = painttype;
  252.     pfont->StrokeWidth = strokewidth;
  253.     pdata = pfont_data(pfont);
  254.     if ( pcharstrings )
  255.       ref_assign(&pdata->CharStrings, pcharstrings);
  256.     else
  257.       make_null(&pdata->CharStrings);
  258.     /* Check that the UniqueIDs match.  This is part of the */
  259.     /* Adobe protection scheme, but we may as well emulate it. */
  260.     if ( uid_is_valid(&pfont->UID) &&
  261.          !dict_check_uid_param(op, &pfont->UID)
  262.        )
  263.       uid_set_invalid(&pfont->UID);
  264.     *ppfont = pfont;
  265.     return 0;
  266. }
  267.  
  268. /* Do the common work for building a font of any non-composite FontType. */
  269. /* The caller guarantees that *op is a dictionary. */
  270. int
  271. build_gs_simple_font(os_ptr op, gs_font_base **ppfont, font_type ftype,
  272.   gs_memory_type_ptr_t pstype, const build_proc_refs *pbuild,
  273.   build_font_options_t options)
  274. {    double bbox[4];
  275.     gs_uid uid;
  276.     int code;
  277.     gs_font_base *pfont;
  278.  
  279.     code = font_bbox_param(op, bbox);
  280.     if ( code < 0 )
  281.       return code;
  282.     if ( (options & bf_FontBBox_required) &&
  283.          bbox[0] == 0 && bbox[1] == 0 && bbox[2] == 0 && bbox[3] == 0
  284.        )
  285.       return_error(e_invalidfont);
  286.     code = dict_uid_param(op, &uid, 0, imemory);
  287.     if ( code < 0 )
  288.       return code;
  289.     if ( (options & bf_UniqueID_ignored) && uid_is_UniqueID(&uid) )
  290.       uid_set_invalid(&uid);
  291.     code = build_gs_font(op, (gs_font **)ppfont, ftype, pstype, pbuild,
  292.                  options);
  293.     if ( code != 0 )    /* invalid or scaled font */
  294.       return code;
  295.     pfont = *ppfont;
  296.     pfont->procs.init_fstack = gs_default_init_fstack;
  297.     pfont->procs.next_char = gs_default_next_char;
  298.     pfont->procs.define_font = gs_no_define_font;
  299.     pfont->procs.make_font = zbase_make_font;
  300.     pfont->FontBBox.p.x = bbox[0];
  301.     pfont->FontBBox.p.y = bbox[1];
  302.     pfont->FontBBox.q.x = bbox[2];
  303.     pfont->FontBBox.q.y = bbox[3];
  304.     pfont->UID = uid;
  305.     lookup_gs_simple_font_encoding(pfont);
  306.     return 0;
  307. }
  308.  
  309. /* Compare the encoding of a simple font with the registered encodings. */
  310. void
  311. lookup_gs_simple_font_encoding(gs_font_base *pfont)
  312. {    const ref *pfe = &pfont_data(pfont)->Encoding;
  313.     int index;
  314.     for ( index = registered_Encodings_countof; --index >= 0; )
  315.       if ( obj_eq(pfe, ®istered_Encoding(index)) )
  316.         break;
  317.     pfont->encoding_index = index;
  318.     if ( index < 0 )
  319.     {    /* Look for an encoding that's "close". */
  320.         int near_index = -1;
  321.         uint esize = r_size(pfe);
  322.         uint best = esize / 3;    /* must match at least this many */
  323.         for ( index = registered_Encodings_countof; --index >= 0; )
  324.         {    const ref *pre = ®istered_Encoding(index);
  325.             bool r_packed = r_has_type(pre, t_shortarray);
  326.             bool f_packed = !r_has_type(pfe, t_array);
  327.             uint match = esize;
  328.             int i;
  329.             ref fchar, rchar;
  330.             const ref *pfchar = &fchar;
  331.             if ( r_size(pre) != esize )
  332.               continue;
  333.             for ( i = esize; --i >= 0; )
  334.             {    uint rnidx;
  335.                 if ( r_packed )
  336.                   rnidx = packed_name_index(pre->value.packed + i);
  337.                 else
  338.                   { array_get(pre, (long)i, &rchar);
  339.                     rnidx = name_index(&rchar);
  340.                   }
  341.                 if ( f_packed )
  342.                   array_get(pfe, (long)i, &fchar);
  343.                 else
  344.                   pfchar = pfe->value.const_refs + i;
  345.                 if ( !r_has_type(pfchar, t_name) ||
  346.                      name_index(pfchar) != rnidx
  347.                    )
  348.                   if ( --match <= best )
  349.                     break;
  350.             }
  351.             if ( match > best )
  352.               best = match,
  353.               near_index = index;
  354.         }
  355.         index = near_index;
  356.     }
  357.     pfont->nearest_encoding_index = index;
  358. }
  359.  
  360. /* Do the common work for building a font of any FontType. */
  361. /* The caller guarantees that *op is a dictionary. */
  362. /* op[-1] must be the key under which the font is being registered */
  363. /* in FontDirectory, normally a name or string. */
  364. /* Return 0 for a new font, 1 for a font made by makefont or scalefont, */
  365. /* or a negative error code. */
  366. private void get_font_name(P2(ref *, const ref *));
  367. private void copy_font_name(P2(gs_font_name *, const ref *));
  368. int
  369. build_gs_font(os_ptr op, gs_font **ppfont, font_type ftype,
  370.   gs_memory_type_ptr_t pstype, const build_proc_refs *pbuild,
  371.   build_font_options_t options)
  372. {    ref kname, fname;        /* t_string */
  373.     ref *pftype;
  374.     ref *pfontname;
  375.     ref *pmatrix;
  376.     gs_matrix mat;
  377.     ref *pencoding = 0;
  378.     bool bitmapwidths;
  379.     int exactsize, inbetweensize, transformedchar;
  380.     int wmode;
  381.     int code;
  382.     gs_font *pfont;
  383.     ref *pfid;
  384.     ref *aop = dict_access_ref(op);
  385.  
  386.     get_font_name(&kname, op - 1);
  387.     if ( dict_find_string(op, "FontType", &pftype) <= 0 ||
  388.          !r_has_type(pftype, t_integer) ||
  389.          pftype->value.intval != (int)ftype ||
  390.          dict_find_string(op, "FontMatrix", &pmatrix) <= 0 ||
  391.          read_matrix(pmatrix, &mat) < 0
  392.        )
  393.       return_error(e_invalidfont);
  394.     if ( dict_find_string(op, "Encoding", &pencoding) <= 0 )
  395.       { if ( !(options & bf_Encoding_optional) )
  396.           return_error(e_invalidfont);
  397.       }
  398.     else
  399.       { if ( !r_is_array(pencoding) )
  400.           return_error(e_invalidfont);
  401.       }
  402.     if ( dict_find_string(op, "FontName", &pfontname) > 0 )
  403.         get_font_name(&fname, pfontname);
  404.     else
  405.         make_empty_string(&fname, a_readonly);
  406.     if ( (code = dict_int_param(op, "WMode", 0, 1, 0, &wmode)) < 0 ||
  407.          (code = dict_bool_param(op, "BitmapWidths", false, &bitmapwidths)) < 0 ||
  408.          (code = dict_int_param(op, "ExactSize", 0, 2, fbit_use_bitmaps, &exactsize)) < 0 ||
  409.          (code = dict_int_param(op, "InBetweenSize", 0, 2, fbit_use_outlines, &inbetweensize)) < 0 ||
  410.          (code = dict_int_param(op, "TransformedChar", 0, 2, fbit_use_outlines, &transformedchar)) < 0
  411.        )
  412.         return code;
  413.     code = dict_find_string(op, "FID", &pfid);
  414.     if ( code > 0 )
  415.     {    if ( !r_has_type(pfid, t_fontID) )
  416.           return_error(e_invalidfont);
  417.         /*
  418.          * If this font has a FID entry already, it might be
  419.          * a scaled font made by makefont or scalefont;
  420.          * in a Level 2 environment, it might be an existing font
  421.          * being registered under a second name, or a re-encoded
  422.          * font (which is questionable PostScript, but dvips
  423.          * is known to do this).
  424.          */
  425.         pfont = r_ptr(pfid, gs_font);
  426.         if ( pfont->base == pfont )    /* original font */
  427.           {    if ( !level2_enabled )
  428.               return_error(e_invalidfont);
  429.             if ( obj_eq(pfont_dict(pfont), op) )
  430.               {    *ppfont = pfont;
  431.                 return 1;
  432.               }
  433.             /*
  434.              * This is a re-encoded font, or some other
  435.              * questionable situation in which the FID
  436.              * was preserved.  Pretend the FID wasn't there.
  437.              */
  438.           }
  439.         else
  440.           {    /* This was made by makefont or scalefont. */
  441.             /* Just insert the new name. */
  442.             code = 1;
  443.             goto set_name;
  444.           }
  445.     }
  446.     /* This is a new font. */
  447.     if ( !r_has_attr(aop, a_write) )
  448.       return_error(e_invalidaccess);
  449.     {    font_data *pdata;
  450.         /* Make sure that we allocate the font data */
  451.         /* in the same VM as the font dictionary. */
  452.         uint space = ialloc_space(idmemory);
  453.  
  454.         ialloc_set_space(idmemory, r_space(op));
  455.         pfont = ialloc_struct(gs_font, pstype,
  456.                       "buildfont(font)");
  457.         pdata = ialloc_struct(font_data, &st_font_data,
  458.                       "buildfont(data)");
  459.         if ( pfont == 0 || pdata == 0 )
  460.           code = gs_note_error(e_VMerror);
  461.         else
  462.           code = add_FID(op, pfont);
  463.         if ( code < 0 )
  464.           {    ifree_object(pdata, "buildfont(data)");
  465.             ifree_object(pfont, "buildfont(font)");
  466.             ialloc_set_space(idmemory, space);
  467.             return code;
  468.           }
  469.         refset_null((ref *)pdata, sizeof(font_data) / sizeof(ref));
  470.         ref_assign_new(&pdata->dict, op);
  471.         ref_assign_new(&pdata->BuildChar, &pbuild->BuildChar);
  472.         ref_assign_new(&pdata->BuildGlyph, &pbuild->BuildGlyph);
  473.         if ( pencoding )
  474.           ref_assign_new(&pdata->Encoding, pencoding);
  475.         /* Clear the chain pointers so as not to confuse the memory */
  476.         /* manager if we bail out after returning from here. */
  477.         pfont->next = pfont->prev = 0;
  478.         pfont->memory = imemory;
  479.         pfont->dir = 0;
  480.         pfont->base = pfont;
  481.         pfont->client_data = pdata;
  482.         pfont->FontType = ftype;
  483.         pfont->FontMatrix = mat;
  484.         pfont->BitmapWidths = bitmapwidths;
  485.         pfont->ExactSize = (fbit_type)exactsize;
  486.         pfont->InBetweenSize = (fbit_type)inbetweensize;
  487.         pfont->TransformedChar = (fbit_type)transformedchar;
  488.         pfont->WMode = wmode;
  489.         pfont->PaintType = 0;
  490.         pfont->StrokeWidth = 0.0;
  491.         pfont->procs.build_char = gs_no_build_char;
  492.         pfont->procs.encode_char = zfont_encode_char;
  493.         pfont->procs.callbacks.glyph_name = zfont_glyph_name;
  494.         pfont->procs.callbacks.known_encode = zfont_known_encode;
  495.         ialloc_set_space(idmemory, space);
  496.     }
  497.     code = 0;
  498. set_name:
  499.     copy_font_name(&pfont->key_name, &kname);
  500.     copy_font_name(&pfont->font_name, &fname);
  501.     *ppfont = pfont;
  502.     return code;
  503. }
  504.  
  505. /* Get the string corresponding to a font name. */
  506. /* If the font name isn't a name or a string, return an empty string. */
  507. private void
  508. get_font_name(ref *pfname, const ref *op)
  509. {    switch ( r_type(op) )
  510.     {
  511.     case t_string:
  512.         *pfname = *op;
  513.         break;
  514.     case t_name:
  515.         name_string_ref(op, pfname);
  516.         break;
  517.     default:
  518.         /* This is weird, but legal.... */
  519.         make_empty_string(pfname, a_readonly);
  520.     }
  521. }
  522.  
  523. /* Copy a font name into the gs_font structure. */
  524. private void
  525. copy_font_name(gs_font_name *pfstr, const ref *pfname)
  526. {    uint size = r_size(pfname);
  527.     if ( size > gs_font_name_max )
  528.         size = gs_font_name_max;
  529.     memcpy(&pfstr->chars[0], pfname->value.const_bytes, size);
  530.     /* Following is only for debugging printout. */
  531.     pfstr->chars[size] = 0;
  532.     pfstr->size = size;
  533. }
  534.  
  535. /* Finish building a font, by calling gs_definefont if needed. */
  536. int
  537. define_gs_font(gs_font *pfont)
  538. {    return (pfont->base == pfont && pfont->dir == 0 ?    /* i.e., unregistered original font */
  539.         gs_definefont(ifont_dir, pfont) :
  540.         0);
  541. }
  542.